package com.lin.service.impl;

import com.aliyun.vod.upload.impl.UploadVideoImpl;
import com.aliyun.vod.upload.req.UploadStreamRequest;
import com.aliyun.vod.upload.resp.UploadStreamResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.vod.model.v20170321.DeleteVideoRequest;
import com.aliyuncs.vod.model.v20170321.DeleteVideoResponse;
import com.aliyuncs.vod.model.v20170321.GetVideoPlayAuthRequest;
import com.aliyuncs.vod.model.v20170321.GetVideoPlayAuthResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lin.entity.Video;
import com.lin.mapper.VideoMapper;
import com.lin.service.VideoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lin.utils.ConstantPropertiesUtils;
import com.lin.utils.InitClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 课程视频 服务实现类
 * </p>
 *
 * @author 霖霖
 * @since 2022-12-24
 */
@Service
@Slf4j
public class VideoServiceImp extends ServiceImpl<VideoMapper, Video> implements VideoService {
    @Override
    public String saveVideo(MultipartFile file) throws IOException {
        //文件原始名
        String fileName = file.getOriginalFilename();
        //设置文件标题，出去后缀
        assert fileName != null;
        String title = fileName.substring(0, fileName.lastIndexOf("."));
        InputStream inputStream = file.getInputStream();
        UploadStreamRequest request = new UploadStreamRequest(
                ConstantPropertiesUtils.KEY_ID, ConstantPropertiesUtils.KEY_SECRET,
                title, fileName, inputStream);
        UploadVideoImpl uploadVideo = new UploadVideoImpl();
        UploadStreamResponse resp = uploadVideo.uploadStream(request);
        String videoId;
        if (resp.isSuccess()) {
            videoId = resp.getVideoId();
        } else {//如果设置回调URL无效，不影响视频上传，可以返回VideoId同时会返回错误码。其他情况上传失败时，VideoId为空，此时需要根据返回错误码分析具体错误原因
            videoId = resp.getVideoId();
            log.error("ErrorCode=" + resp.getCode());
            log.error("ErrorMessage" + resp.getMessage());
        }
        return videoId;
    }

    @Override
    public boolean deleteVideo(String videoId) {
        Video video = baseMapper.selectById(videoId);
        DefaultAcsClient client = InitClient.initVodClient(ConstantPropertiesUtils.KEY_ID,
                ConstantPropertiesUtils.KEY_SECRET);
        DeleteVideoRequest request = new DeleteVideoRequest();
        if (delete(client, request, video.getVideoSourceId())) {
            return baseMapper.deleteById(videoId) > 0;
        }
        return false;
    }

    @Override
    @Transactional
    public boolean deleteVideoBatch(String chapterId) {
        QueryWrapper<Video> videoQueryWrapper = new QueryWrapper<>();
        videoQueryWrapper.eq("chapter_id", chapterId);
        return preDelete(videoQueryWrapper);
    }

    @Override
    public boolean removeVideoBatch(String courseId) {
        QueryWrapper<Video> videoQueryWrapper = new QueryWrapper<>();
        videoQueryWrapper.eq("course_id", courseId);
        return preDelete(videoQueryWrapper);
    }


    @Override
    @Transactional
    public boolean swapUpdateVideo(Video video, Video conflictVideo) {
        QueryWrapper<Video> videoQueryWrapper = new QueryWrapper<>();
        videoQueryWrapper.select("sort", "start_time");
        videoQueryWrapper.eq("id", video.getId());
        //查询除修改前的序号
        Video oldVideo = baseMapper.selectOne(videoQueryWrapper);
        LocalDateTime startTime = conflictVideo.getStartTime();
        conflictVideo.setStartTime(oldVideo.getStartTime());
        conflictVideo.setSort(oldVideo.getSort());
        video.setStartTime(startTime);
        return baseMapper.updateById(conflictVideo) > 0 && baseMapper.updateById(video) > 0;

    }

    @Override
    public LocalDateTime getPreVideo(Video video) {
        //SELECT * FROM video where course_id=18 and sort<3 ORDER BY sort DESC LIMIT 1;
        QueryWrapper<Video> videoQueryWrapper = new QueryWrapper<>();
        videoQueryWrapper.eq("course_id", video.getCourseId());
        videoQueryWrapper.lt("sort", video.getSort());
        videoQueryWrapper.orderByDesc("sort");
        videoQueryWrapper.last("limit 1");
        videoQueryWrapper.select("start_time");
        Video preVideo = baseMapper.selectOne(videoQueryWrapper);
        return preVideo.getStartTime();
    }

    @Override
    public LocalDateTime getNextVideo(Video video) {
        //SELECT * from video where course_id=18 and sort>3 ORDER BY sort LIMIT 1;
        QueryWrapper<Video> videoQueryWrapper = new QueryWrapper<>();
        videoQueryWrapper.eq("course_id", video.getCourseId());
        videoQueryWrapper.gt("sort", video.getSort());
        videoQueryWrapper.orderByAsc("sort");
        videoQueryWrapper.last("limit 1");
        videoQueryWrapper.select("start_time");
        Video nextVideo = baseMapper.selectOne(videoQueryWrapper);
        if (nextVideo != null && nextVideo.getStartTime() != null)
            return nextVideo.getStartTime();
        return null;
    }

    @Override
    public String getPlayAuth(String videoSourceId) throws ClientException {
        DefaultAcsClient client = InitClient.initVodClient(ConstantPropertiesUtils.KEY_ID,ConstantPropertiesUtils.KEY_SECRET);
        //获取凭证
        GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
        request.setVideoId(videoSourceId);
        GetVideoPlayAuthResponse response = client.getAcsResponse(request);
        return response.getPlayAuth();
    }

    @Override
    public boolean updatePlayCount(String videoSourceId) {
        long l = baseMapper.updatePlayCount(videoSourceId);
        return l>0;
    }

    @Override
    public Long statisticsCount(LocalDateTime yesterdays) {

        return baseMapper.selectStatisticCount(yesterdays);
    }

    private boolean preDelete(QueryWrapper<Video> videoQueryWrapper) {
        List<Video> videos = baseMapper.selectList(videoQueryWrapper);
        ArrayList<String> videoSourceIds = new ArrayList<>();
        for (Video video : videos) {
            videoSourceIds.add(video.getVideoSourceId());
        }
        DefaultAcsClient client = InitClient.initVodClient(ConstantPropertiesUtils.KEY_ID, ConstantPropertiesUtils.KEY_SECRET);
        DeleteVideoRequest request = new DeleteVideoRequest();
        String join = StringUtils.join(videoSourceIds.toArray(), ",");
        if (delete(client, request, join)) {
            int num = baseMapper.delete(videoQueryWrapper);
            return num > 0;
        }
        return false;
    }

    private boolean delete(DefaultAcsClient client, DeleteVideoRequest request, String join) {
        DeleteVideoResponse response;
        request.setVideoIds(join);
        try {
            response = client.getAcsResponse(request);
            log.info("RequestId= " + response.getRequestId());
            return true;
        } catch (ClientException e) {
            log.info("ErrorMessage=" + e.getLocalizedMessage());
            return false;
        }
    }
}
